﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using TTServer.Objects;
using TTServer.Messages;

using libReadWrite;
using libCommonClass;
using libAsymmetricEncryption;
using libInterface;

namespace TTServer
{
    public abstract class ServerThread : IClientInfoProvider
    {
        protected Thread _receivingThread = null;
        protected Thread _sendingThread = null;

        protected BigEndianReader _bigEndianReader = null;
        protected BigEndianWriter _bigEndianWriter = null;

        protected MessageReader _msgReader = null;

        /// <summary>
        /// /////////////////////////////////////////////////////
        /// </summary>
        private int _clientID = -1;

        public int ClientID
        {
            get { return _clientID; }
            set { _clientID = value; }
        }

        private int _authority = AuthorityConstant.GUEST;
        private string _temporaryKey = "";

        //private int _authority = AuthorityConstant.ADMIN;
        //private string _temporaryKey = "asdfghjkl";

        public int Authority
        {
            get { return _authority; }
            set { _authority = value; }
        }

        public string TemporaryKey
        {
            get { return _temporaryKey; }
            set { _temporaryKey = value; }
        }

        private RSA_Key _clientPublicKey;

        public RSA_Key ClientPublicKey
        {
            get { return _clientPublicKey; }
            set { _clientPublicKey = value; }
        }

        //public BigEndianWriter getWriter()
        //{
        //   return _bigEndianWriter;
        //}

        private CMessageQueue _msgQueue = new CMessageQueue();

        /// <summary>
        /// ////////////////////////////////////////////////////////
        /// </summary>

        public ServerThread()
        {
            ClientID = Global.getClientID();
        }

        public void CreateAndStartThread()
        {
            _receivingThread = new Thread(new ThreadStart(ReceivingThreadFunction));
            _receivingThread.Name = "receivingThread " + Global.getCount().ToString();
            _receivingThread.IsBackground = true;
            _receivingThread.Priority = ThreadPriority.Normal;
            _receivingThread.Start();

            _sendingThread = new Thread(new ThreadStart(SendingThreadFunction));
            _sendingThread.Name = "sendingThread " + Global.getCount().ToString();
            _sendingThread.IsBackground = true;
            _sendingThread.Priority = ThreadPriority.Normal;
            _sendingThread.Start();
        }

        public void AddToMessageQueue(TTMessage msg)
        {
            _msgQueue.Enqueue(msg);
        }

        public void ReceivingThreadFunction()
        {
            try
            {
                TTMessage msg = null;

                while (true)
                {
                    try
                    {
                        msg = _msgReader.GetMessage();

                        if (msg != null)
                        {
                            GlobalDispatcher.AddToQueue(new CTask(this, msg));
                        }
                        else
                        {
                            NotifyMessage nm = new NotifyMessage("Operation invalid");
                            nm.WriteMessage(_bigEndianWriter);
                        }
                    }
                    catch (Exception ex)
                    {
                        //try
                        //{
                        //    NotifyMessage nm = new NotifyMessage("The connection no longer works.");
                        //    nm.WriteMessage(_bigEndianWriter);
                        //
                        //    System.Threading.Thread.Sleep(3000);
                        //
                        //    this.Terminate();
                        //}
                        //catch
                        //{ 
                        //
                        //}
                        System.Console.WriteLine(ex.Message);
                        return;
                    }
                }
            }
            catch
            {
                return;
            }
        }

        public void SendingThreadFunction()
        {
            try
            {
                TTMessage msg = null;

                while (true)
                {
                    try
                    {
                        msg = _msgQueue.Dequeue();

                        msg.WriteMessage(this._bigEndianWriter);
                    }
                    catch(Exception ex)
                    {
                        System.Console.WriteLine(ex.Message);
                        return;
                    }
                }
            }
            catch
            {
                return;
            }
        }

        public virtual void Terminate()
        {
            try
            {
                _receivingThread.Abort();
                _sendingThread.Abort();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
}
